using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LevelData;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GGJ11
{
    class LayerEnemy : LayerGameObject
    {
        private Level level;
        Animation enemyIdleRed;
        Animation enemyRunRed;
        Animation enemyDieRed;
        Animation enemyJustDieRed;
        Animation enemyAttackRed;
        Animation enemyHitRed;

        Animation enemyIdleYellow;
        Animation enemyRunYellow;
        Animation enemyDieYellow;
        Animation enemyJustDieYellow;
        Animation enemyAttackYellow;
        Animation enemyHitYellow;

        Animation enemyIdleGreen;
        Animation enemyRunGreen;
        Animation enemyDieGreen;
        Animation enemyJustDieGreen;
        Animation enemyAttackGreen;
        Animation enemyHitGreen;

        Animation playerHit;

        Animation bladeRun;
        Animation thorns;

        public LayerEnemy(ContentManager content) : base(content)
        {
            level = content.ServiceProvider.GetService(typeof(Level)) as Level;
            enemyRunRed = new Animation(content.Load<Texture2D>("Sprites/MonsterA/RunEnemy"), 0.05f, true);
            enemyDieRed = new Animation(content.Load<Texture2D>("Sprites/MonsterA/dieEnemy"), 0.05f, false);
            enemyJustDieRed = new Animation(content.Load<Texture2D>("Sprites/MonsterA/enemyJustDie"), 0.05f, false);
            enemyIdleRed = new Animation(content.Load<Texture2D>("Sprites/MonsterA/Idle"), 0.15f, true);
            enemyAttackRed = new Animation(content.Load<Texture2D>("Sprites/MonsterA/attack"), 0.05f, false);
            enemyHitRed = new Animation(content.Load<Texture2D>("Sprites/MonsterA/hit"), 0.1f, false);
            

            enemyRunYellow = new Animation(content.Load<Texture2D>("Sprites/MonsterYellow/run"), 0.05f, true);
            enemyDieYellow = new Animation(content.Load<Texture2D>("Sprites/MonsterYellow/dienemy"), 0.05f, false);
            enemyJustDieYellow = new Animation(content.Load<Texture2D>("Sprites/MonsterYellow/enemyJustDie"), 0.05f, false);
            enemyIdleYellow = new Animation(content.Load<Texture2D>("Sprites/MonsterYellow/Idle"), 0.15f, true);
            enemyAttackYellow = new Animation(content.Load<Texture2D>("Sprites/MonsterYellow/attack"), 0.05f, false);
            enemyHitYellow = new Animation(content.Load<Texture2D>("Sprites/MonsterYellow/hit"), 0.1f, false);

            enemyRunGreen = new Animation(content.Load<Texture2D>("Sprites/MonsterGreen/run"), 0.05f, true);
            enemyDieGreen = new Animation(content.Load<Texture2D>("Sprites/MonsterGreen/dienemy"), 0.05f, false);
            enemyJustDieGreen = new Animation(content.Load<Texture2D>("Sprites/MonsterGreen/enemyJustDie"), 0.05f, false);
            enemyIdleGreen = new Animation(content.Load<Texture2D>("Sprites/MonsterGreen/Idle"), 0.15f, true);
            enemyAttackGreen = new Animation(content.Load<Texture2D>("Sprites/MonsterGreen/attack"), 0.05f, false);
            enemyHitGreen = new Animation(content.Load<Texture2D>("Sprites/MonsterGreen/hit"), 0.1f, false);

            playerHit = new Animation(content.Load<Texture2D>("Sprites/Player/hit"), 0.1f, false);

            bladeRun = new Animation(content.Load<Texture2D>("Sprites/Guill"), 0.1f, true);
            thorns = new Animation(content.Load<Texture2D>("Sprites/Thorns"), 0.1f, true);

            Initialize();
        }


        public void Initialize()
        {
            for (int i = 0; i < level.enemyList.Count; i++)
            {
                if (level.enemyList[i].type == EnemyType.Monster)
                {
                    if (level.enemyList[i].die)
                    {
                        switch (level.enemyList[i].color)
                        {
                            case ColorEnemy.Red:
                                level.enemyList[i].sprite.PlayAnimation(enemyJustDieRed);
                                break;
                            case ColorEnemy.Yellow:
                                level.enemyList[i].sprite.PlayAnimation(enemyJustDieYellow);
                                break;
                            case ColorEnemy.Green:
                                level.enemyList[i].sprite.PlayAnimation(enemyJustDieGreen);
                                break;
                        }
                    }
                    else
                    {
                        switch (level.enemyList[i].color)
                        {
                            case ColorEnemy.Red:
                                level.enemyList[i].sprite.PlayAnimation(enemyRunRed);
                                break;
                            case ColorEnemy.Yellow:
                                level.enemyList[i].sprite.PlayAnimation(enemyRunYellow);
                                break;
                            case ColorEnemy.Green:
                                level.enemyList[i].sprite.PlayAnimation(enemyRunGreen);
                                break;
                        }

                        level.enemyList[i].health = (int)(Math.Log((double)(level.numLevel)) + 1);
                        level.enemyList[i].localBounds = new Rectangle(25, -40, (int)(30), (int)(80));
                    }
                }
                else if (level.enemyList[i].type == EnemyType.Guillottine)
                {
                    level.enemyList[i].sprite.PlayAnimation(bladeRun);
                    level.enemyList[i].localBounds = new Rectangle(0, 0, 30, 30);
                }
                else if (level.enemyList[i].type == EnemyType.Thorns)
                {
                    level.enemyList[i].sprite.PlayAnimation(thorns);
                    level.enemyList[i].localBounds = new Rectangle(0, 30, 45, 20);
                }
            }
        }
        //this function move the enemies and check if player collide with one enemy
        public void Update(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

            //foreach(enemy e in level.enemyList)
            for (int i = 0; i < level.enemyList.Count; i++)
            {
                if (!level.enemyList[i].die)
                {
                    // Calculate tile position based on the side we are walking towards.
                    float posX = level.enemyList[i].position.X;
                    int tileX = (int)Math.Round(posX / Tile.Width);
                    int tileY = (int)Math.Floor(level.enemyList[i].position.Y / Tile.Height);

                    if (level.enemyList[i].hit)
                    {
                        switch (level.enemyList[i].color)
                        {
                            case ColorEnemy.Red:
                                level.enemyList[i].sprite.PlayAnimation(enemyRunRed);
                                break;
                            case ColorEnemy.Yellow:
                                level.enemyList[i].sprite.PlayAnimation(enemyRunYellow);
                                break;
                            case ColorEnemy.Green:
                                level.enemyList[i].sprite.PlayAnimation(enemyRunGreen);
                                break;
                        }
                        level.enemyList[i].hit = false;
                    }

                    if (level.enemyList[i].timeAttack > 0)
                    {
                        level.enemyList[i].timeAttack -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                    }

                    if (!level.enemyList[i].onFighting)
                    {
                        level.enemyList[i].timeAttackToAttack -= (float)gameTime.ElapsedGameTime.TotalSeconds;

                        if (level.enemyList[i].timeAttackToAttack <= 0)
                        {
                            level.enemyList[i].timeAttackToAttack = 1;
                            level.enemyList[i].onFighting = true;
                            switch (level.enemyList[i].color)
                            {
                                case ColorEnemy.Red:
                                    level.enemyList[i].sprite.PlayAnimation(enemyRunRed);
                                    break;
                                case ColorEnemy.Yellow:
                                    level.enemyList[i].sprite.PlayAnimation(enemyRunYellow);
                                    break;
                                case ColorEnemy.Green:
                                    level.enemyList[i].sprite.PlayAnimation(enemyRunGreen);
                                    break;
                            }
                        }

                    }

                    if (level.enemyList[i].waitTime > 0)
                    {
                        if (level.enemyList[i].type == EnemyType.Guillottine)
                        {
                            level.enemyList[i].direction = (FaceDirection)(-(int)level.enemyList[i].direction);
                            level.enemyList[i].waitTime = 0;
                        }
                        else
                        {
                            // Wait for some amount of time.
                            level.enemyList[i].waitTime = Math.Max(0.0f, level.enemyList[i].waitTime - (float)gameTime.ElapsedGameTime.TotalSeconds);

                            if (level.enemyList[i].waitTime <= 0.0f)
                            {
                                // Then turn around.
                                level.enemyList[i].direction = (FaceDirection)(-(int)level.enemyList[i].direction);
                                if (level.enemyList[i].type == EnemyType.Monster)
                                    switch (level.enemyList[i].color)
                                    {
                                        case ColorEnemy.Red:
                                            level.enemyList[i].sprite.PlayAnimation(enemyRunRed);
                                            break;
                                        case ColorEnemy.Yellow:
                                            level.enemyList[i].sprite.PlayAnimation(enemyRunYellow);
                                            break;
                                        case ColorEnemy.Green:
                                            level.enemyList[i].sprite.PlayAnimation(enemyRunGreen);
                                            break;
                                    }
                            }
                        }
                    }
                    else
                    {
                        switch (level.enemyList[i].type)
                        {
                            case EnemyType.Monster:
                                {
                                    // If we are about to run into a wall or off a cliff, start waiting.
                                    if (level.GetCollision(tileX + (int)level.enemyList[i].direction, tileY) == TileCollision.Impassable ||
                                        level.GetCollision(tileX + (int)level.enemyList[i].direction, tileY -1) == TileCollision.Impassable
                                        || level.GetCollision(tileX + (int)level.enemyList[i].direction, tileY +1) == TileCollision.Passable)
                                    {
                                        level.enemyList[i].waitTime = level.enemyList[i].MaxWaitTime;
                                        switch (level.enemyList[i].color)
                                        {
                                            case ColorEnemy.Red:
                                                level.enemyList[i].sprite.PlayAnimation(enemyIdleRed);
                                                break;
                                            case ColorEnemy.Yellow:
                                                level.enemyList[i].sprite.PlayAnimation(enemyIdleYellow);
                                                break;
                                            case ColorEnemy.Green:
                                                level.enemyList[i].sprite.PlayAnimation(enemyIdleGreen);
                                                break;
                                        }
                                    }
                                    else if (level.enemyList[i].onFighting)
                                    {
                                        //   Move in the current direction.
                                        Vector2 velocity = new Vector2((int)level.enemyList[i].direction * level.enemyList[i].MoveSpeed * elapsed, 0.0f);
                                        level.enemyList[i].position = level.enemyList[i].position + velocity;
                                    }
                                    break;
                                }
                            case EnemyType.Guillottine:
                                {
                                    int checkPosition;
                                    // If we are about to run into a wall or off a cliff, start waiting.
                                    if (level.enemyList[i].direction == FaceDirection.Left)
                                        checkPosition = (int)level.enemyList[i].direction;
                                    else
                                        checkPosition = (int)level.enemyList[i].direction - 1;

                                        if (level.GetCollision(tileX, tileY - checkPosition) == TileCollision.Impassable)
                                        {
                                            level.enemyList[i].waitTime = level.enemyList[i].MaxWaitTime;
                                        }
                                        else
                                        {
                                            // Move in the current direction.
                                            Vector2 velocity = new Vector2(0.0f, (int)(level.enemyList[i].direction) * level.enemyList[i].MoveSpeed * elapsed);
                                            level.enemyList[i].position = level.enemyList[i].position - velocity;
                                        }
                                        break;
                                }
                        }
                    }

                        //check if player collide with enemies
                        if (CheckForAttack(i) && level.playerLevel.dieTime <= 0)
                        {
                            if (level.playerLevel.timeAttack <= 0 && level.enemyList[i].type != EnemyType.Thorns && !level.enemyList[i].onFighting && level.enemyList[i].timeAttackToAttack == 1
                                && level.playerLevel.invulnerability <= 0)
                            {
                                level.playerLevel.sprite.PlayAnimation(playerHit);
                                level.playerLevel.hitByEnemy = true;
                                level.playerLevel.health--;
                                if (level.playerLevel.health <= 0)
                                {
                                    level.playerLevel.isAlive = false;
                                    level.playerLevel.dieTime = 3.0f;
                                    level.menuDieTime = 1.0f;
                                    level.soundList.Add(SoundType.diePlayer);
                                }
                            }
                            else
                            {
                                if (level.enemyList[i].type == EnemyType.Monster && level.playerLevel.timeAttack > 0 && !level.playerLevel.hit)
                                {
                                    switch (level.enemyList[i].color)
                                    {
                                        case ColorEnemy.Red:
                                            level.enemyList[i].sprite.PlayAnimation(enemyHitRed);
                                            break;
                                        case ColorEnemy.Yellow:
                                            level.enemyList[i].sprite.PlayAnimation(enemyHitYellow);
                                            break;
                                        case ColorEnemy.Green:
                                            level.enemyList[i].sprite.PlayAnimation(enemyHitGreen);
                                            break;
                                    }
                                    level.enemyList[i].hit = true;
                                    level.enemyList[i].health--;
                                    level.playerLevel.hit = true;
                                    if (level.enemyList[i].health <= 0)
                                    {
                                        switch (level.enemyList[i].color)
                                        {
                                            case ColorEnemy.Red:
                                                level.enemyList[i].sprite.PlayAnimation(enemyDieRed);
                                                break;
                                            case ColorEnemy.Yellow:
                                                level.enemyList[i].sprite.PlayAnimation(enemyDieYellow);
                                                break;
                                            case ColorEnemy.Green:
                                                level.enemyList[i].sprite.PlayAnimation(enemyDieGreen);
                                                break;
                                        }
                                        level.enemyList[i].die = true;
                                        level.playerLevel.points += (200 * (level.numLevel / 2 + 1));
                                        level.soundList.Add(SoundType.dieEnemy);
                                    }
                                }
                            }
                        }

                        if (level.playerLevel.invulnerability <= 0)
                        {
                        if (level.enemyList[i].type == EnemyType.Thorns)
                        {
                            if (level.playerLevel.BoundingRectangle.Intersects(level.enemyList[i].BoundingRectangle))
                            {
                                if (level.playerLevel.velocity.X > 250 || level.playerLevel.velocity.X < -250
                                    || level.playerLevel.velocity.Y > 10)
                                {
                                    level.playerLevel.isAlive = false;
                                    level.playerLevel.dieTime = 3.0f;
                                    level.menuDieTime = 1.0f;
                                    level.soundList.Add(SoundType.diePlayer);
                                }
                            }
                        }

                        if (level.enemyList[i].type == EnemyType.Guillottine)
                        {
                            if (level.playerLevel.BoundingRectangle.Intersects(level.enemyList[i].BoundingRectangle))
                            {
                                level.playerLevel.isAlive = false;
                                level.playerLevel.dieTime = 3.0f;
                                level.menuDieTime = 1.0f;
                                level.soundList.Add(SoundType.diePlayer);
                            }
                        }
                    }

                }
            }
            base.Update(gameTime);
        }

        private bool CheckForAttack(int index)
        {
                Rectangle rectAttackEnemy = level.enemyList[index].BoundingRectangle;
                Rectangle rectAttackPlayer = level.playerLevel.BoundingRectangle;

                rectAttackEnemy.Width += 20;
                rectAttackPlayer.Width += 30;

                if (level.playerLevel.orientationSx)
                {
                    rectAttackPlayer.X -= 30;
                }

                if (rectAttackEnemy.Intersects(rectAttackPlayer))
                {
                    if (level.enemyList[index].type == EnemyType.Monster && level.enemyList[index].onFighting && level.enemyList[index].timeAttackToAttack == 1)
                    {
                        if (level.enemyList[index].position.X > level.playerLevel.position.X)
                        {
                            if (level.enemyList[index].direction == FaceDirection.Left)
                            {
                                Random RollDiceShot = new Random();
                                switch (level.enemyList[index].color)
                                {
                                    case ColorEnemy.Red:
                                        level.enemyList[index].sprite.PlayAnimation(enemyAttackRed);
                                        break;
                                    case ColorEnemy.Yellow:
                                        level.enemyList[index].sprite.PlayAnimation(enemyAttackYellow);
                                        break;
                                    case ColorEnemy.Green:
                                        level.enemyList[index].sprite.PlayAnimation(enemyAttackGreen);
                                        break;
                                }
                                if (RollDiceShot.Next() % 10 < 3)
                                {
                                    level.enemyList[index].onFighting = false;
                                }
                                level.soundList.Add(SoundType.battleEnemy);
                            }
                        }
                        else
                        {
                            if (level.enemyList[index].direction == FaceDirection.Right)
                            {
                                Random RollDiceShot = new Random();
                                switch (level.enemyList[index].color)
                                {
                                    case ColorEnemy.Red:
                                        level.enemyList[index].sprite.PlayAnimation(enemyAttackRed);
                                        break;
                                    case ColorEnemy.Yellow:
                                        level.enemyList[index].sprite.PlayAnimation(enemyAttackYellow);
                                        break;
                                    case ColorEnemy.Green:
                                        level.enemyList[index].sprite.PlayAnimation(enemyAttackGreen);
                                        break;
                                }
                                if (RollDiceShot.Next() % 10 < 3)
                                {
                                    level.enemyList[index].onFighting = false;
                                }
                                level.soundList.Add(SoundType.battleEnemy);
                            }
                        }
                    }
                    return true;
                }
                return false;
        }


        //update service when load the next level
        public void UpdateLevelService(ContentManager content)
        {
            level = content.ServiceProvider.GetService(typeof(Level)) as Level;
            this.Initialize();
            base.UpdateLevelService(content);
        }

    }
}
